package com.cn.sl.server.api.system.user.model.dto

import com.cn.sl.server.api.system.user.service.AdminUserService
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.Constraint
import jakarta.validation.ConstraintValidator
import jakarta.validation.ConstraintValidatorContext
import jakarta.validation.constraints.NotBlank
import org.dromara.hutool.extra.spring.SpringUtil
import org.springframework.messaging.handler.annotation.Payload
import kotlin.reflect.KClass

@Schema(description = "修改登录用户基本信息")
@PhoneUniqueCheck
class UpdateLoginUserInfoParams(
    @field:Schema(description = "头像id")
    var avatarId: Long?,
    @field:NotBlank(message = "用户名不能为空")
    @field:Schema(description = "用户名")
    var username: String?,
    override var phone: String?,
    /**
     * 用户首页id
     */
    @field:Schema(description = "用户首页id")
    var homePageId: Long? = null
) : PhoneCheckParam(null, phone) {
    fun toDto(): UpdateLoginUserInfoDto {
        return UpdateLoginUserInfoDto(this)
    }
}

data class UpdateLoginUserInfoDto(
    val avatarId: Long?,
    val username: String,
    val phone: String,
    val homePageId: Long?
) {
    constructor(param: UpdateLoginUserInfoParams) : this(
        avatarId = param.avatarId,
        username = param.username!!,
        phone = param.phone!!,
        homePageId = param.homePageId
    )
}

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = [PhoneUniqueCheckValidator::class])
annotation class PhoneUniqueCheck(
    val message: String = "手机号码已被注册",
    val groups: Array<KClass<*>> = [],
    val payload: Array<KClass<out Payload>> = [],
)

class PhoneUniqueCheckValidator : ConstraintValidator<PhoneUniqueCheck, PhoneCheckParam> {
    override fun isValid(
        value: PhoneCheckParam?,
        context: ConstraintValidatorContext?
    ): Boolean {
        value?.let {
            val adminUserService = SpringUtil.getBean(AdminUserService::class.java)
            return adminUserService.phoneExists(UserPhoneExistDto(it.phone!!, it.id))
        } ?: return false
    }
}